package com.qijian.maindata.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qijian.common.core.domain.entity.SysDictData;
import com.qijian.common.exception.ServiceException;
import com.qijian.common.utils.*;
import com.qijian.common.utils.mybatis.WhereEntityTool;
import com.qijian.common.utils.uuid.IdUtils;
import com.qijian.maindata.domain.Process;
import com.qijian.maindata.domain.*;
import com.qijian.maindata.domain.dto.LineProcessExport;
import com.qijian.maindata.domain.query.*;
import com.qijian.maindata.domain.vo.LineProcessBomVo;
import com.qijian.maindata.domain.vo.LineProcessDataVo;
import com.qijian.maindata.domain.vo.LineProcessVo;
import com.qijian.maindata.mapper.LineProcessMapper;
import com.qijian.maindata.service.*;
import com.qijian.system.domain.SysConfig;
import com.qijian.system.mapper.SysConfigMapper;
import com.qijian.tool.domain.Storage;
import com.qijian.tool.service.IStorageService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 工艺Service业务层处理
 *
 * @author qijian
 * @date 2021-09-03
 */
@Service
@RequiredArgsConstructor
public class LineProcessServiceImpl extends ServiceImpl<LineProcessMapper, LineProcess> implements ILineProcessService {

    private final LineProcessMapper lineProcessMapper;
    private final ILineProcessItemService lineProcessItemService;
    private final ILineProcessTimeService lineProcessTimeService;
    private final ILineProcessWorkService lineProcessWorkService;
    private final ILineProcessSchemeService lineProcessSchemeService;
    private final ILineService lineService;
    private final IBomDetailService bomDetailService;
    private final IStorageService storageService;

    private final IProcessService processService;


    private final SysConfigMapper sysConfigMapper;

    @Override
    public List<LineProcessVo> listVo(Wrapper<LineProcessQuery> queryWrapper) {
        return lineProcessMapper.selectVo(queryWrapper);
    }

    @Override
    public List<LineProcessVo> listAndImageVo(Wrapper<LineProcessQuery> queryWrapper) {
        return lineProcessMapper.selectImageVo(queryWrapper);
    }

    @Override
    public List<LineProcessBomVo> groupByTypeName(Long bomId, Boolean isTree, String typeName, Boolean isOut) {
        List<LineProcessBomVo> result = new ArrayList<>();
        List<LineProcessBomVo> lineProcessVoList;
        lineProcessVoList = lineProcessMapper.groupByTypeName(bomId, typeName, isOut);

        if (!isTree) {
            return lineProcessVoList;
        }

        Map<String, String> map = new HashMap<>();
        lineProcessVoList.forEach(process -> {
            if (map.get(process.getProcessTypeName()) == null) {
                map.put(process.getProcessTypeName(), process.getProcessTypeName());
                result.add(process);
            }
        });
        List<LineProcessBomVo> finalLineProcessVoList = lineProcessVoList;
        result.forEach(process -> {
            process.setChild(BeanUtil.copyToList(finalLineProcessVoList.stream().filter(action -> process.getProcessTypeName().equals(action.getProcessTypeName())).collect(Collectors.toList()), LineProcessBomVo.class));
            BigDecimal workTime = BigDecimal.ZERO;
            BigDecimal workCost = BigDecimal.ZERO;
            Integer total = 0;
            for (LineProcessBomVo vo : process.getChild()) {
                vo.setProcessId(vo.getProcessId() + 1);
                vo.setWorkCost(vo.getWorkCost().multiply(BigDecimal.valueOf(vo.getCount())));
                vo.setWorkTime(vo.getWorkTime().multiply(BigDecimal.valueOf(vo.getCount())));
                workCost = workCost.add(vo.getWorkCost());
                workTime = workTime.add(vo.getWorkTime());
                vo.setTotal(vo.getCount());
                total += vo.getTotal();
                vo.setItemWeight(null);
                vo.setProcessTypeName(null);
            }
            process.setProcessName(null);
            process.setDrawingNo(null);
            process.setPartNo(null);
            process.setRemark(null);
            process.setWorkCost(workCost);
            process.setWorkTime(workTime);
            process.setTotal(total);
        });
        return result;
    }

    @Override
    public List<LineProcessBomVo> listByTypeName(Long bomId, Boolean isTree, String typeName, Boolean isOut) {
        List<LineProcessBomVo> result = new ArrayList<>();
        List<LineProcessBomVo> lineProcessVoList;
        lineProcessVoList = lineProcessMapper.listByTypeName(bomId, typeName, isOut);


        if (!isTree) {
            return lineProcessVoList;
        }

        Map<String, String> map = new HashMap<>();
        lineProcessVoList.forEach(process -> {
            if (map.get(process.getProcessTypeName()) == null) {
                map.put(process.getProcessTypeName(), process.getProcessTypeName());
                result.add(process);
            }
        });
        List<LineProcessBomVo> finalLineProcessVoList = lineProcessVoList;
        result.forEach(process -> {
            process.setChild(BeanUtil.copyToList(finalLineProcessVoList.stream().filter(action -> process.getProcessTypeName().equals(action.getProcessTypeName())).collect(Collectors.toList()), LineProcessBomVo.class));
            BigDecimal workTime = BigDecimal.ZERO;
            BigDecimal workCost = BigDecimal.ZERO;
            int changeSize = 0;
            Integer total = 0;
            for (LineProcessBomVo vo : process.getChild()) {
                vo.setProcessId(vo.getProcessId() + 1);
                vo.setWorkCost(vo.getWorkCost().multiply(BigDecimal.valueOf(vo.getCount())));
                vo.setWorkTime(vo.getWorkTime().multiply(BigDecimal.valueOf(vo.getCount())));
                workCost = workCost.add(vo.getWorkCost());
                workTime = workTime.add(vo.getWorkTime());
                vo.setTotal(vo.getCount());
                total += vo.getTotal();
                vo.setItemWeight(null);
                vo.setProcessTypeName(null);
                changeSize += vo.getChangeSize();
            }
            process.setProcessName(null);
            process.setDrawingNo(null);
            process.setPartNo(null);
            process.setRemark(null);
            process.setWorkCost(workCost);
            process.setWorkTime(workTime);
            process.setTotal(total);
            process.setChangeSize(changeSize);
         });
        return result;
    }

    @Override
    public List<LineProcessBomVo> listByTypeName4de(Long bomId, Boolean isTree, String typeName, Boolean isOut, String requestType) {

        List<LineProcessBomVo> result = new ArrayList<>();
        List<LineProcessBomVo> lineProcessVoList;

        // 如果来源是定额申请 类型为数控件那么需要过滤工序名称
        if ("2".equals(requestType)) {
            SysConfig config = sysConfigMapper.checkConfigKeyUnique("skj_price_process_name_list");
            if (null == config || StringUtils.isEmpty(config.getConfigValue())) {
                throw new ServiceException("E01:数控件异常: 数控件工序参数未设置 [skj_price_process_name_list] ");
            }
            List<String> processNameList = Arrays.stream(config.getConfigValue().split(",")).collect(Collectors.toList());
            lineProcessVoList = lineProcessMapper.listByTypeName4DE(bomId, typeName, isOut, processNameList);
        } else {
            lineProcessVoList = lineProcessMapper.listByTypeName(bomId, typeName, isOut);
        }

        if (CollUtil.isNotEmpty(lineProcessVoList)) {
            for (LineProcessBomVo lineProcessBomVo : lineProcessVoList) {
                //厚度thickness
                if (StrUtil.isNotBlank(lineProcessBomVo.getItemAttr())) {
                    if (StringUtils.isNotEmpty(lineProcessBomVo.getItemAttr()) &&
                            lineProcessBomVo.getItemAttr().startsWith("[") &&
                            lineProcessBomVo.getItemAttr().endsWith("]")) {
                        String thickness = getThickness(lineProcessBomVo);
                        if (StrUtil.isNotBlank(thickness)) {
                            lineProcessBomVo.setThickness(thickness);
                        }
                    }
                }

            }
        }

        if (!isTree) {
            lineProcessVoList.forEach(process -> {
                process.setWorkCost(process.getWorkCost().multiply(BigDecimal.valueOf(process.getCount())));
                process.setWorkTime(process.getWorkTime().multiply(BigDecimal.valueOf(process.getCount())));
            });
            return lineProcessVoList;
        }

        Map<String, String> map = new HashMap<>();
        lineProcessVoList.forEach(process -> {
            if (map.get(process.getProcessTypeName()) == null) {
                map.put(process.getProcessTypeName(), process.getProcessTypeName());
                result.add(process);
            }
        });

        List<LineProcessBomVo> finalLineProcessVoList = lineProcessVoList;
        result.forEach(process -> {
            process.setChild(BeanUtil.copyToList(finalLineProcessVoList.stream().filter(action -> process.getProcessTypeName().equals(action.getProcessTypeName())).collect(Collectors.toList()), LineProcessBomVo.class));
            BigDecimal workTime = BigDecimal.ZERO;
            BigDecimal workCost = BigDecimal.ZERO;
            int changeSize = 0;
            Integer total = 0;
            for (LineProcessBomVo vo : process.getChild()) {
                vo.setProcessId(vo.getProcessId() + 1);
                vo.setWorkCost(vo.getWorkCost().multiply(BigDecimal.valueOf(vo.getCount())));
                vo.setWorkTime(vo.getWorkTime().multiply(BigDecimal.valueOf(vo.getCount())));
                workCost = workCost.add(vo.getWorkCost());
                workTime = workTime.add(vo.getWorkTime());
                vo.setTotal(vo.getCount());
                total += vo.getTotal();
                vo.setItemWeight(null);
                vo.setProcessTypeName(null);
                changeSize += vo.getChangeSize();
            }
            process.setProcessName(null);
            process.setDrawingNo(null);
            process.setPartNo(null);
            process.setRemark(null);
            process.setWorkCost(workCost);
            process.setWorkTime(workTime);
            process.setTotal(total);
            process.setChangeSize(changeSize);
         });
        return result;
    }

    //获取厚度
    private static String getThickness(LineProcessBomVo lineProcessBomVo) {
        JSONArray jsonArray = new JSONArray(lineProcessBomVo.getItemAttr());
        String thickness = "";
        for (Object obj : jsonArray) {
            JSONObject json = new JSONObject(obj);
            String key = json.getStr("name");
            String value = json.getStr("value");
            if ("厚".equals(key)) {
                thickness = value;
            }
        }
        return thickness;
    }

    @Override
    public List<LineProcess> lineMaxSort(Set<Long> lineIds) {
        QueryWrapper<LineProcess> wrapper = new QueryWrapper<>();
        wrapper.select("line_id,Max(sort) as sort");
        wrapper.in("line_id", lineIds);
        wrapper.groupBy("line_id");
        return this.list(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BomDetail saveData(BomDetail bom, Line line, List<LineProcess> lineProcesss) {
        if (CollectionUtil.isEmpty(lineProcesss)) {
            throw new ServiceException("工序列表为空！");
        }

        // 附件
        List<Storage> files = new ArrayList<>(16);

        Long lineId = lineProcesss.get(0).getLineId();
        String lineCode = lineProcesss.get(0).getLineCode();
        boolean isCheck = false;
        if (line != null) {
            if (ObjectUtil.isNull(line.getLineId())) {
                line.setLineId(IdUtils.singletonSnowId());
                if (StringUtils.isNotBlank(line.getLineCode())) {
                    LineQuery lineQuery = new LineQuery();
                    lineQuery.setLineCode(line.getLineCode());
                    long count = lineService.count(WhereEntityTool.invoke(lineQuery));
                    if (count > 0) {
                        throw new ServiceException("工艺路线编码已存在！");
                    }

                    LineBom lineBom = new LineBom();
                    lineBom.setLineId(line.getLineId());
                    lineBom.setItemId(bom.getItemId());
                    lineBom.setBomId(bom.getDetailId());
                    lineService.saveDetail(Collections.singletonList(lineBom));
                } else {
                    line.setLineCode(IdUtils.getNumber("GYXL-", lineProcessMapper.countCurrentDateWithDel() + 1));
                }

                line.setLineVersion("1.0");
                line.setIsDisabled(false);
                line.setIsDefault("N");
                List<LineBom> lineBomList = new ArrayList<>();
                LineBom lineBom = new LineBom();
                lineBom.setLineId(line.getLineId());
                lineBom.setBomId(bom.getDetailId());
                lineBom.setItemId(bom.getItemId());
                lineBomList.add(lineBom);
                line.setLineBomList(lineBomList);
                lineService.save(line);
                isCheck = true;
            } else {
                lineService.updateById(line);
            }
            lineId = line.getLineId();
            lineCode = line.getLineCode();
            bom.setLineId(lineId);
            bom.setLineCode(lineCode);
            bomDetailService.updateById(bom);
        }
        // 工作单元-新增
        List<LineProcessWork> addProcessWorks = new ArrayList<>(16);
        // 工作人员-新增
        List<LineProcessTime> addProcessTimes = new ArrayList<>(16);
        // 物料需求-新增
        List<LineProcessItem> addProcessItems = new ArrayList<>(16);

        // 工序-排除
        Set<Long> processIdsNot = new HashSet<>(16);
        // 作业单元-排除
        Set<Long> processWorkIdsNot = new HashSet<>(16);
        // 作业人员-排除
        Set<Long> processTimeIdsNot = new HashSet<>(16);
        // 物料需求-排除
        Set<Long> processItemIdsNot = new HashSet<>(16);
        int sort = 1;
        boolean finalIsCheck = isCheck;
        for (LineProcess process : lineProcesss) {
            if (finalIsCheck) {
                process.setProcessId(null);
            }
            if (process.getCreateId() == null) {
                process.setCreateId(SecurityUtils.getUserId());
            }
            process.setLineId(lineId);
            process.setLineCode(lineCode);
            process.setSort(sort);
            sort++;
            if (ObjectUtil.isNotNull(process.getProcessId())) {
                processIdsNot.add(process.getProcessId());
            }
        }

        // 移除不在工序列表中数据
        LineProcessQuery processQuery = new LineProcessQuery();
        processQuery.setLineId(lineId);
        processQuery.setIdsNot(processIdsNot);
        //  检验下游是否有已完成的工单，有的话无法删除工序
        this.checkOrder(processQuery);
        this.remove(WhereEntityTool.invoke(processQuery));

        //报检方案
        List<LineProcessScheme> processSchemeList = new ArrayList<>();
        Set<Long> processIds = new HashSet<>();
        // 工序更新
        if (CollectionUtil.isNotEmpty(lineProcesss)) {
            lineProcesss.forEach(process -> {
                process.setCreateId(process.getCreateId() == null ? SecurityUtils.getUserId() : process.getCreateId());
                if (CollUtil.isNotEmpty(process.getProcessSchemeList())) {
                    process.setIsSchemeCheck(true);
                }
            });
            this.saveOrUpdateBatch(lineProcesss);

            processIds = lineProcesss.stream().map(LineProcess::getProcessId).collect(Collectors.toSet());

            //报检方案,置空id
            lineProcesss.forEach(process -> {
                if (CollUtil.isNotEmpty(process.getProcessSchemeList())) {
                    process.getProcessSchemeList().forEach(s -> {
                        s.setId(null);
                        s.setProcessId(process.getProcessId());
                        processSchemeList.add(s);
                    });
                }
            });
        }
        //清空旧的报检方案
        if (CollUtil.isNotEmpty(processIds)) {
            lineProcessSchemeService.remove(new LambdaQueryWrapper<LineProcessScheme>().in(LineProcessScheme::getProcessId, processIds));
        }
        //保存方案
        if (CollUtil.isNotEmpty(processSchemeList)) {
            lineProcessSchemeService.saveBatch(processSchemeList);
        }

        // 更新附件
        lineProcesss.forEach(process -> {
            if (CollectionUtil.isNotEmpty(process.getFiles())) {
                process.getFiles().forEach(file -> {
                    if (ObjectUtil.isNotNull(file)) {
                        file.setClassId(process.getProcessId());
                        file.setClassTable(LineProcess.class.getSimpleName());
                        files.add(file);
                    }
                });
            }
        });

        if (CollectionUtil.isNotEmpty(files)) {
            storageService.updateBatchById(files);
        }

        for (LineProcess process : lineProcesss) {
            process.getProcessWorkList().forEach(work -> {
                if (finalIsCheck) {
                    work.setUnitId(null);
                }
                work.setLineId(process.getLineId());
                work.setLineCode(process.getLineCode());
                work.setProcessId(process.getProcessId());
                work.setProcessCode(process.getProcessCode());
                if (ObjectUtil.isNotNull(work.getUnitId())) {
                    processWorkIdsNot.add(work.getUnitId());
                }
                addProcessWorks.add(work);
            });
            process.getProcessTimeList().forEach(time -> {
                if (StringUtils.isNotBlank(time.getTypeName()) && StringUtils.isNotBlank(time.getWorkName())) {
                    if (finalIsCheck) {
                        time.setWorkId(null);
                    }
                    time.setLineId(process.getLineId());
                    time.setLineCode(process.getLineCode());
                    time.setProcessId(process.getProcessId());
                    time.setProcessCode(process.getProcessCode());
                    if (ObjectUtil.isNotNull(time.getWorkId())) {
                        processTimeIdsNot.add(time.getWorkId());
                    }
                    addProcessTimes.add(time);
                }
            });
            process.getProcessItemList().forEach(item -> {
                if (finalIsCheck) {
                    item.setDemandId(null);
                }
                item.setProducerId(SecurityUtils.getUserId());
                item.setProducerName(SecurityUtils.getNickName());
                item.setBomId(bom.getDetailId());
                item.setLineId(process.getLineId());
                item.setLineCode(process.getLineCode());
                item.setProcessId(process.getProcessId());
                item.setProcessCode(process.getProcessCode());
                if (ObjectUtil.isNotNull(item.getDemandId())) {
                    processItemIdsNot.add(item.getDemandId());
                }
                addProcessItems.add(item);
            });
        }

        // 移除不在作业单元列表中数据
        LineProcessWorkQuery processWorkQuery = new LineProcessWorkQuery();
        processWorkQuery.setLineId(lineId);
        if (CollectionUtil.isNotEmpty(processWorkIdsNot)) {
            processWorkQuery.setIdsNot(processWorkIdsNot);
        }
        lineProcessWorkService.remove(WhereEntityTool.invoke(processWorkQuery));
        // 作业单元更新
        if (CollectionUtil.isNotEmpty(addProcessWorks)) {
            lineProcessWorkService.saveOrUpdateBatch(addProcessWorks);
        }

        // 移除不在作业工种列表中数据
        LineProcessTimeQuery processTimeQuery = new LineProcessTimeQuery();
        processTimeQuery.setLineId(lineId);
        if (CollectionUtil.isNotEmpty(processTimeIdsNot)) {
            processTimeQuery.setIdsNot(processTimeIdsNot);
        }
        lineProcessTimeService.remove(WhereEntityTool.invoke(processTimeQuery));
        // 作业工种更新
        if (CollectionUtil.isNotEmpty(addProcessTimes)) {
            lineProcessTimeService.saveOrUpdateBatch(addProcessTimes);
        }

        // 移除不在物料需求列表中数据
        LineProcessItemQuery processItemQuery = new LineProcessItemQuery();
        processItemQuery.setLineId(lineId);
        if (CollectionUtil.isNotEmpty(processItemIdsNot)) {
            processItemQuery.setIdsNot(processItemIdsNot);
        }
        lineProcessItemService.remove(WhereEntityTool.invoke(processItemQuery));
        // 物料需求更新
        if (CollectionUtil.isNotEmpty(addProcessItems)) {
            lineProcessItemService.saveOrUpdateBatch(addProcessItems);
        }

        // 绑定外购件
        if (CollUtil.isNotEmpty(lineProcesss) && ObjectUtils.isNotNull(bom.getDetailId())) {
            LineProcessItemQuery itemQuery = new LineProcessItemQuery();
            itemQuery.setBomId(bom.getDetailId());
            itemQuery.setLineIdIsNull(true);
            List<LineProcessItem> processItemList = lineProcessItemService.list(WhereEntityTool.invoke(itemQuery));
            if (CollUtil.isNotEmpty(processItemList)) {
                processItemList.forEach(item -> {
                    item.setLineId(lineProcesss.get(0).getLineId());
                    item.setLineCode(lineProcesss.get(0).getLineCode());
                    item.setProcessId(lineProcesss.get(0).getProcessId());
                    item.setProcessCode(lineProcesss.get(0).getProcessCode());
                    lineProcessItemService.updateBatchById(processItemList);
                });
            }
        }

        return bom;
    }

    // 校验下游是否存在已验收的工单
    private void checkOrder(LineProcessQuery query) {
        //2025-01-17 去除限制
        return;
        /*
        List<LineProcess> processList = this.list(WhereEntityTool.invoke(query));
        if (CollUtil.isEmpty(processList)) {
            return;
        }
        List<String> workCodes = this.baseMapper.selectAcceptProcessOrder(processList.stream().map(LineProcess::getProcessId).collect(Collectors.toSet()));
        if (CollUtil.isEmpty(workCodes)) {
            return;
        }
        throw new ServiceException(StringUtils.format("下游存在已验收的工单 {}，无法删除工序", workCodes));
    */
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addBatchLine(List<LineProcessDataVo> resources) {
        resources.forEach(action -> this.saveData(action.getBom(), action.getLine(), action.getLineProcesss()));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void copy(Long lineId) {
        Line line = lineService.getById(lineId);
        if (ObjectUtil.isNull(line) || ObjectUtil.isNull(line.getLineId())) {
            throw new ServiceException("E01:工艺线路信息错误！");
        }
        // 线路
        LineQuery lineQuery = new LineQuery();
        lineQuery.setLineClassify(line.getLineClassify());
        String lineCodeOld = line.getLineCode();
        line.setLineCode("GYXL-" + (StringUtils.isNotEmpty(line.getLineClassify()) ? line.getLineClassify().toUpperCase() + "-" : "") + String.format("%06d", lineService.count(WhereEntityTool.invoke(lineQuery)) + 1));
        line.setLineId(null);
        line.setCreateBy(null);
        line.setCreateTime(null);
        line.setLineVersion(VersionUtils.autoUpgradeVersion(line.getLineVersion()));
        line.setIsDefault("N");
        lineService.save(line);
        // 线路工艺
        LineProcessQuery processQuery = new LineProcessQuery();
        processQuery.setLineCode(lineCodeOld);
        List<LineProcess> processList = this.list(WhereEntityTool.invoke(processQuery));
        if (CollectionUtil.isNotEmpty(processList)) {
            Set<Long> processIds = new HashSet<>(processList.size());
            processList.forEach(process -> {
                processIds.add(process.getProcessId());
                process.setProcessId(null);
                process.setLineCode(line.getLineCode());
                process.setCreateBy(null);
                process.setCreateTime(null);
            });
            // 生产单元
            LineProcessWorkQuery processWorkQuery = new LineProcessWorkQuery();
            processWorkQuery.setLineCode(lineCodeOld);
            processWorkQuery.setProcessIds(processIds);
            List<LineProcessWork> processWorkList = lineProcessWorkService.list(WhereEntityTool.invoke(processWorkQuery));
            processWorkList.forEach(work -> {
                work.setUnitId(null);
                work.setLineCode(line.getLineCode());
                work.setCreateBy(null);
                work.setCreateTime(null);
            });
            // 作业人员
            LineProcessTimeQuery processStaffQuery = new LineProcessTimeQuery();
            processStaffQuery.setLineCode(lineCodeOld);
            processStaffQuery.setIds(processIds);
            List<LineProcessTime> processTimeList = lineProcessTimeService.list(WhereEntityTool.invoke(processStaffQuery));
            processTimeList.forEach(staff -> {
                staff.setWorkId(null);
                staff.setLineCode(line.getLineCode());
                staff.setCreateBy(null);
                staff.setCreateTime(null);
            });
            // 物料需求
            LineProcessItemQuery processItemQuery = new LineProcessItemQuery();
            processItemQuery.setLineCode(lineCodeOld);
            processItemQuery.setProcessIds(processIds);
            List<LineProcessItem> processItemList = lineProcessItemService.list(WhereEntityTool.invoke(processItemQuery));
            processItemList.forEach(item -> {
                item.setDemandId(null);
                item.setLineCode(line.getLineCode());
                item.setCreateBy(null);
                item.setCreateTime(null);
            });

            if (CollectionUtil.isNotEmpty(processWorkList)) {
                lineProcessWorkService.saveBatch(processWorkList);
            }
            if (CollectionUtil.isNotEmpty(processTimeList)) {
                lineProcessTimeService.saveBatch(processTimeList);
            }
            if (CollectionUtil.isNotEmpty(processItemList)) {
                lineProcessItemService.saveBatch(processItemList);
            }
        }
    }

    @Override
    public List<LineProcessBomVo> selectProcessVo(QueryWrapper<LineProcessQuery> queryWrapper) {
        return lineProcessMapper.selectProcessAndBomVo(queryWrapper);
    }

    @Override
    public List<LineProcessBomVo> selectEcnProcessVo(LineProcessQuery query, Integer type) {
        return lineProcessMapper.selectEcnProcessAndBomVo(query, query.getCreateTimeList().get(0), query.getCreateTimeList().get(1), type);
    }

    @Override
    public List<LineProcessVo> getProcessType(Long bomId) {
        return lineProcessMapper.getProcessByBomId(bomId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean editProcess(List<LineProcess> lineProcesss) {
        Long lineId = lineProcesss.get(0).getLineId();
        String lineCode = lineProcesss.get(0).getLineCode();

        // 附件
        List<Storage> files = new ArrayList<>(16);
        // 工作单元-新增
        List<LineProcessWork> addProcessWorks = new ArrayList<>(16);
        // 工作人员-新增
        List<LineProcessTime> addProcessTimes = new ArrayList<>(16);
        // 物料需求-新增
        List<LineProcessItem> addProcessItems = new ArrayList<>(16);

        // 工序-排除
        Set<Long> processIdsNot = new HashSet<>(16);
        // 作业单元-排除
        Set<Long> processWorkIdsNot = new HashSet<>(16);
        // 作业人员-排除
        Set<Long> processTimeIdsNot = new HashSet<>(16);
        // 物料需求-排除
        Set<Long> processItemIdsNot = new HashSet<>(16);
        int sort = 1;
        for (LineProcess process : lineProcesss) {
            if (process.getCreateId() == null) {
                process.setCreateId(SecurityUtils.getUserId());
            }
            process.setLineId(lineId);
            process.setLineCode(lineCode);
            process.setSort(sort);
            sort++;
            if (ObjectUtil.isNotNull(process.getProcessId())) {
                processIdsNot.add(process.getProcessId());
            }
        }

        // 移除不在工序列表中数据
        LineProcessQuery processQuery = new LineProcessQuery();
        processQuery.setLineId(lineId);
        processQuery.setIdsNot(processIdsNot);
        //  检验下游是否有已完成的工单，有的话无法删除工序
        this.checkOrder(processQuery);
        this.remove(WhereEntityTool.invoke(processQuery));

        // 工序更新
        if (CollectionUtil.isNotEmpty(lineProcesss)) {
            lineProcesss.forEach(process -> process.setCreateId(process.getCreateId() == null ? SecurityUtils.getUserId() : process.getCreateId()));
            this.saveOrUpdateBatch(lineProcesss);
        }

        // 更新附件
        lineProcesss.forEach(process -> {
            if (CollectionUtil.isNotEmpty(process.getFiles())) {
                process.getFiles().forEach(file -> {
                    if (ObjectUtil.isNotNull(file)) {
                        file.setClassId(process.getProcessId());
                        file.setClassTable(LineProcess.class.getSimpleName());
                        files.add(file);
                    }
                });
            }
        });

        if (CollectionUtil.isNotEmpty(files)) {
            storageService.updateBatchById(files);
        }

        for (LineProcess process : lineProcesss) {
            process.getProcessWorkList().forEach(work -> {
                work.setLineId(process.getLineId());
                work.setLineCode(process.getLineCode());
                work.setProcessId(process.getProcessId());
                work.setProcessCode(process.getProcessCode());
                if (ObjectUtil.isNotNull(work.getUnitId())) {
                    processWorkIdsNot.add(work.getUnitId());
                }
                addProcessWorks.add(work);
            });
            process.getProcessTimeList().forEach(time -> {
                if (StringUtils.isNotBlank(time.getTypeName()) && StringUtils.isNotBlank(time.getWorkName())) {
                    time.setLineId(process.getLineId());
                    time.setLineCode(process.getLineCode());
                    time.setProcessId(process.getProcessId());
                    time.setProcessCode(process.getProcessCode());
                    if (ObjectUtil.isNotNull(time.getWorkId())) {
                        processTimeIdsNot.add(time.getWorkId());
                    }
                    addProcessTimes.add(time);
                }
            });
            process.getProcessItemList().forEach(item -> {
                item.setProducerId(SecurityUtils.getUserId());
                item.setProducerName(SecurityUtils.getNickName());
                item.setBomId(process.getProcessItemList().get(0).getBomId());
                item.setLineId(process.getLineId());
                item.setLineCode(process.getLineCode());
                item.setProcessId(process.getProcessId());
                item.setProcessCode(process.getProcessCode());
                if (ObjectUtil.isNotNull(item.getDemandId())) {
                    processItemIdsNot.add(item.getDemandId());
                }
                addProcessItems.add(item);
            });
        }

        // 移除不在作业单元列表中数据
        LineProcessWorkQuery processWorkQuery = new LineProcessWorkQuery();
        processWorkQuery.setLineId(lineId);
        if (CollectionUtil.isNotEmpty(processWorkIdsNot)) {
            processWorkQuery.setIdsNot(processWorkIdsNot);
        }
        lineProcessWorkService.remove(WhereEntityTool.invoke(processWorkQuery));
        // 作业单元更新
        if (CollectionUtil.isNotEmpty(addProcessWorks)) {
            lineProcessWorkService.saveOrUpdateBatch(addProcessWorks);
        }

        // 移除不在作业工种列表中数据
        LineProcessTimeQuery processTimeQuery = new LineProcessTimeQuery();
        processTimeQuery.setLineId(lineId);
        if (CollectionUtil.isNotEmpty(processTimeIdsNot)) {
            processTimeQuery.setIdsNot(processTimeIdsNot);
        }
        lineProcessTimeService.remove(WhereEntityTool.invoke(processTimeQuery));
        // 作业工种更新
        if (CollectionUtil.isNotEmpty(addProcessTimes)) {
            lineProcessTimeService.saveOrUpdateBatch(addProcessTimes);
        }

        // 移除不在物料需求列表中数据
        LineProcessItemQuery processItemQuery = new LineProcessItemQuery();
        processItemQuery.setLineId(lineId);
        if (CollectionUtil.isNotEmpty(processItemIdsNot)) {
            processItemQuery.setIdsNot(processItemIdsNot);
        }
        lineProcessItemService.remove(WhereEntityTool.invoke(processItemQuery));
        // 物料需求更新
        if (CollectionUtil.isNotEmpty(addProcessItems)) {
            lineProcessItemService.saveOrUpdateBatch(addProcessItems);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void exportProcess(Long bomId, List<LineProcessExport> list) {
        BomDetailQuery detailQuery = new BomDetailQuery();
        detailQuery.setBomId(bomId);
        detailQuery.setItemCodeList(list.stream().map(LineProcessExport::getItemCode).collect(Collectors.toList()));
        List<BomDetail> detailList = bomDetailService.list(WhereEntityTool.invoke(detailQuery));
        if (CollUtil.isNotEmpty(detailList)) {
            Map<String, BomDetail> detailMap = new HashMap<>(detailList.size());
            Set<Long> lineIds = new HashSet<>(detailList.size());
            Set<Long> bomIds = new HashSet<>(detailList.size());
            detailList.forEach(detail -> {
                detailMap.put(detail.getItemCode(), detail);
                if (detail.getLineId() != null) {
                    lineIds.add(detail.getLineId());
                }
                bomIds.add(detail.getDetailId());
            });
            List<BomDetail> bomDetails = new ArrayList<>(detailList.size());

            Map<Long, List<LineProcess>> lineProcessMap = new HashMap<>(detailList.size());
            Map<Long, Line> lineMap = new HashMap<>(detailList.size());
            if (CollUtil.isNotEmpty(lineIds)) {
                LineProcessQuery processQuery = new LineProcessQuery();
                processQuery.setLineIds(lineIds);
                lineProcessMap = this.list(WhereEntityTool.invoke(processQuery)).stream().collect(Collectors.groupingBy(LineProcess::getLineId));
            }

            List<LineProcessItem> processItems = new ArrayList<>(detailList.size());
            // 字典
            Map<String, String> processTypeDict = DictUtils.getDictCache("process_type").stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
            // 用料
            LineProcessItemQuery processItemQuery = new LineProcessItemQuery();
            processItemQuery.setBomIds(bomIds);
            processItemQuery.setLineIdIsNull(true);
            Map<Long, List<LineProcessItem>> processItemMap = lineProcessItemService.list(WhereEntityTool.invoke(processItemQuery)).stream().collect(Collectors.groupingBy(LineProcessItem::getBomId));
            // 工序
            Map<String, Process> processDataMap = new HashMap<>(16);
            // 未查询到工序
            List<Process> processeAdds = new ArrayList<>(16);
            long lineCount = lineProcessMapper.countCurrentDateWithDel() + 1;
            for (LineProcessExport detail : list) {
                BomDetail bomDetail = detailMap.get(detail.getItemCode());
                if (bomDetail != null && StringUtils.isNotBlank(detail.getLineProcess())) {
                    List<LineProcess> processList = new ArrayList<>(8);
                    if (ObjectUtil.isNotNull(bomDetail.getLineId())) {
                        processList = lineProcessMap.get(bomDetail.getLineId());
                    }

                    String[] processAry = detail.getLineProcess().split("-");
                    for (int i = 0; i < processAry.length; i++) {
                        Process process = processDataMap.get(processAry[i]);
                        if (ObjectUtil.isNull(process)) {
                            ProcessQuery processQuery = new ProcessQuery();
                            processQuery.setNameEq(processAry[i]);
                            List<Process> processes = processService.list(WhereEntityTool.invoke(processQuery));
                            if (CollUtil.isNotEmpty(processes)) {
                                process = processes.get(0);
                            } else {
                                process = new Process();
                                process.setId(IdUtils.singletonSnowId());
                                process.setName(processAry[i]);
                                processeAdds.add(process);
                            }
                            processDataMap.put(processAry[i], process);
                        }

                        if (ObjectUtil.isNotNull(process) && ObjectUtil.isNotNull(process.getId())) {
                            Line line = new Line();
                            if (CollUtil.isEmpty(processList)) {
                                line.setLineId(IdUtils.singletonSnowId());
                                line.setLineCode(IdUtils.getNumber("GYXL-", lineCount + lineMap.size()));
                                line.setLineName(String.format("%s(%s.%s)", detail.getItemName(), detail.getDrawnNo(), detail.getPartNo()));
                                line.setLineVersion("1.0");
                                line.setIsDisabled(false);
                                line.setIsDefault("N");
                                lineMap.put(line.getLineId(), line);
                            } else {
                                line.setLineId(processList.get(0).getLineId());
                                line.setLineCode(processList.get(0).getLineCode());
                            }
                            LineProcess lineProcess = new LineProcess();
                            lineProcess.setProcessId(IdUtils.singletonSnowId());
                            lineProcess.setLineId(line.getLineId());
                            lineProcess.setLineCode(line.getLineCode());
                            lineProcess.setPid(process.getId());
                            lineProcess.setProcessName(process.getName());
                            lineProcess.setProcessCode(process.getCode());
                            lineProcess.setProcessType(process.getType());
                            lineProcess.setProcessTypeName(processTypeDict.get(process.getType()));
                            lineProcess.setReportMode("手动报工");
                            lineProcess.setSort(CollUtil.isNotEmpty(processList) ? processList.get(processList.size() - 1).getSort() + 1 : 1);
                            lineProcess.setIsOut(lineProcess.getProcessName().contains("外协"));
                            lineProcess.setIsDefault(true);
                            lineProcess.setPlanCode(lineProcess.getSort() + "");
                            lineProcess.setPlanSystem(IdUtils.simpleUUID().replace("-", ""));
                            lineProcess.setCode("1");
                            processList.add(lineProcess);

                            if (ObjectUtil.isNull(bomDetail.getLineId())) {
                                bomDetail.setLineId(line.getLineId());
                                bomDetail.setLineCode(line.getLineCode());
                                bomDetails.add(bomDetail);
                            }
                            lineProcessMap.put(bomDetail.getLineId(), processList);

                            List<LineProcessItem> processItemList = processItemMap.get(bomDetail.getDetailId());
                            if (CollUtil.isNotEmpty(processItemList)) {
                                for (LineProcessItem action : processItemList) {
                                    action.setLineId(line.getLineId());
                                    action.setLineCode(line.getLineCode());
                                    action.setProcessId(processList.get(0).getProcessId());
                                    action.setProcessCode(processList.get(0).getProcessCode());
                                }
                                processItems.addAll(processItemList);
                            }
                        }
                    }
                }
            }

            if (CollUtil.isNotEmpty(lineMap)) {
                lineService.saveBatch(lineMap.values());
            }
            if (CollUtil.isNotEmpty(processeAdds)) {
                processService.saveBatch(processeAdds);
            }
            if (CollUtil.isNotEmpty(lineProcessMap)) {
                List<LineProcess> lineProcesses = new ArrayList<>(20);
                lineProcessMap.forEach((key, value) -> lineProcesses.addAll(value));
                this.saveOrUpdateBatch(lineProcesses);
            }
            if (CollUtil.isNotEmpty(bomDetails)) {
                bomDetailService.updateBatchById(bomDetails);
            }
            if (CollUtil.isNotEmpty(processItems)) {
                lineProcessItemService.updateBatchById(processItems);
            }
        }
    }


    @Override
    public int updateProcessByProcessId(Long mainId) {
        return lineProcessMapper.updateProcessByProcessId(mainId);
    }

    @Override
    public void updateProcessOrderByDeProcessId(Long mainId) {
        lineProcessMapper.updateProcessOrderByDeProcessId(mainId);
    }

    @Override
    public void updateProcessOrderFactoryByDeProcessId(Long mainId) {
        lineProcessMapper.updateProcessOrderFactoryByDeProcessId(mainId);
    }




}
